package br.perfiman.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;

import br.perfiman.dao.AbstractDAOService;
import br.perfiman.model.AbstractEntity;

/**
 * Main implementation for PerFiMan's Persistence Services
 *
 * @author Wagner Costa
 * @since 27/12/2007
 * @version 1.0
 *
 * @param <Entity>
 */
public abstract class AbstractDAOServiceBean<Entity extends AbstractEntity> implements AbstractDAOService<Entity> {

    protected EntityManager em;

    public void setEm(EntityManager em) {
		this.em = em;
	}

	public AbstractDAOServiceBean() {
		em = getEntityManager();
	}

    /**
     * Return a EntityManager instance from subclass
     *
     * @author Wagner Costa
     * @since 27/12/2007
     * @version 1.0
     * @return
     */
    public abstract EntityManager getEntityManager();

    @SuppressWarnings("unchecked")
	private Class<Entity> getEntityClass() {
		return (Class<Entity>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
    }

	public Entity insert(Entity entity) throws Exception{
		try{
			updateEntityManager();
			em.persist(entity);
			return entity;
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		}
	}

	public Entity update(Entity entity) throws Exception{
		try{
			updateEntityManager();
			em.merge(entity);
			return entity;
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		}
	}

	public void remove(Entity entity) throws Exception{
		try{
			updateEntityManager();
			entity = retrieveById(entity.getEntityId());
			em.remove(entity);
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		}
	}

	public Entity retrieveById(Object id) throws Exception{
		try{
			updateEntityManager();
			return (Entity) em.find(getEntityClass(), id);
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		}
	}

	@SuppressWarnings("unchecked")
	public List<Entity> retrieveAll() throws Exception{
		try{
			updateEntityManager();
			return em.createQuery("FROM " + getEntityClass().getName()).getResultList();
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		}
	}

	private void updateEntityManager(){
		if(em == null)
			em = getEntityManager();
	}
	
}
